package com.ftg.learn.back.pattern.factory;

import com.ftg.learn.back.pattern.factory.reflech.DefaultVal;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 *
 * @author kangjx
 * @createTime 2022/9/1
 */
public class ProductFactory {

    /**
     * 通过工厂返回大量的产品
     * @return
     */
    public static Product getProductInfo(String type){
        if(type.equals("food")){
            return new FoodImpl();
        }else if(type.equals("electronic")){
            return new ElectronicImpl();
        }
        return null;
    }

    /**
     * 通过enum来完成工厂模式
     * @param type
     * @return
     */
    public static Product getProductInfo(ProductType type){
        if(type == ProductType.FOOD){
            return new FoodImpl();
        }else if(type == ProductType.Electronic){
            return new ElectronicImpl();
        }
        return null;
    }

    /**
     * 通过反射的方式来完成当前工厂生成类的过程
     *
     *  这样写完成以后，class的泛型 只能是product 以及子类
     * Class<Product> c
     *  你传递过来的这个类要是product的子类，或者实现类
     * Class<? extends Product> c
     *  设计感 更强  解决多实现类  复杂结构功能更强一些
     * @param c  反射
     *           map<Class,Object> knowmap = new ConcurrentHashMap<>();
     * @return
     */
    public static Product getProductInfo(Class<? extends Product> c){
        try {
            Product t1 = c.newInstance();
            Field[] fs = c.getDeclaredFields();
            for (int i = 0; i < fs.length; i++) {
                Field temp = fs[i];
                PropertyDescriptor propertyDescriptor = new PropertyDescriptor(temp.getName(),c);
                Method writeMethod = propertyDescriptor.getWriteMethod();

                DefaultVal val = temp.getAnnotation(DefaultVal.class);
                if(val != null){
                    if(fs[i].getGenericType().getTypeName().contains("Integer")){
                        writeMethod.invoke(t1,new Integer(val.value()));
                    }else{
                        writeMethod.invoke(t1,val.value());
                    }
                }
            }

            return t1;
        } catch (InstantiationException | IllegalAccessException | IntrospectionException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

//    效率高 map spring ioc 容器 map<Class,Object> knowmap = new ConcurrentHashMap<>();

}
